package org.steven.crm.core.service.weixin;

import org.steven.crm.core.dto.weixin.CreatePayRequest;
import org.steven.crm.core.dto.weixin.PayParamDto;
import org.steven.crm.core.exception.ServiceException;
import org.steven.crm.core.utils.wx.MD5Util;
import org.steven.crm.core.utils.wx.Sha1Util;
import org.steven.crm.core.utils.wx.TenpayUtil;
import org.steven.crm.core.utils.wx.WeixinUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import org.apache.log4j.Logger;

/**
 * @Author wuzw
 * @Date 2023/6/27 14:15
 * @Version 1.0
 */
public class WeixinPayService {
    private static Logger logger = Logger.getLogger(WeixinUserService.class);

    public PayParamDto createWXAppPayParas(CreatePayRequest request) throws Exception {
        String currTime = TenpayUtil.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = TenpayUtil.buildRandom(4) + "";
        String strReq = strTime + strRandom;


        String nonce_str = strReq;
        String body = "订单支付";
        String attach = "";

        String trade_type = request.getTradeType();
        SortedMap<String, String> packageParams = new TreeMap<>();
        packageParams.put("appid", request.getWxAppId());
        packageParams.put("mch_id", request.getWxPartner());
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("out_trade_no", request.getTransactionId());
        packageParams.put("total_fee", request.getAmount() + "");
        packageParams.put("spbill_create_ip", request.getIp());
        packageParams.put("notify_url", request.getNotifyUrl());
        packageParams.put("trade_type", trade_type);
        if (StringUtils.isNotEmpty(request.getOpenId())) {
            packageParams.put("openid", request.getOpenId());
        }


        String sign = createSign(packageParams, request.getWxPartnerKey(), "UTF-8");
        String xml="<xml>"+
                "<appid>" + request.getWxAppId() + "</appid>" +
                "<mch_id>" + request.getWxPartner() + "</mch_id>" +
                "<nonce_str>" + nonce_str + "</nonce_str>" +
                "<sign>" + sign + "</sign>" +
                "<body><![CDATA[" + body + "]]></body>" +
                "<attach>" + attach + "</attach>"+
                "<out_trade_no>" + request.getTransactionId() + "</out_trade_no>" +
                "<attach>" + attach + "</attach>" +
                "<total_fee>" + request.getAmount() + "</total_fee>" +
                "<spbill_create_ip>" + request.getIp() + "</spbill_create_ip>"+
                "<notify_url>" + request.getNotifyUrl() + "</notify_url>" +
                "<trade_type>" + trade_type + "</trade_type>" +
                (StringUtils.isNotEmpty(request.getOpenId()) ? "<openid>" + request.getOpenId() + "</openid>" : "") +
                "</xml>";
        String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        Map<String, String> wxPayResult = WeixinUtil.getWxResultMap(createOrderURL, xml);
        if (wxPayResult == null) {
            throw new ServiceException("统一支付接口获取预支付订单出错");
        }

        PayParamDto payParamDto = new PayParamDto();
        if (request.getTradeType().equals("JSAPI")) {
            String prepayId = wxPayResult.get("prepay_id");
            if (prepayId.equals("")) {
                throw new ServiceException("统一支付接口获取预支付订单出错");
            }
            SortedMap<String, String> finalpackage = new TreeMap<>();
            String timestamp = Sha1Util.getTimeStamp();
            String packages = "prepay_id=" + prepayId;
            finalpackage.put("appId", request.getWxAppId());
            finalpackage.put("timeStamp", timestamp);
            finalpackage.put("nonceStr", nonce_str);
            finalpackage.put("package", packages);
            finalpackage.put("signType", "MD5");
            String finalSign = createSign(finalpackage, request.getWxPartnerKey(), "UTF-8");

            payParamDto.setAppId(request.getWxAppId());
            payParamDto.setTimeStamp(timestamp);
            payParamDto.setNonceStr(nonce_str);
            payParamDto.setPackages(packages);
            payParamDto.setSignType("MD5");
            payParamDto.setPaySign(finalSign);
        } else if (request.getTradeType().equals("NATIVE")) {
            payParamDto.setCodeUrl(wxPayResult.get("code_url"));
        }

        return payParamDto;
    }

    private String createSign(SortedMap<String, String> packageParams, String key, String charset) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k)
                    && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + key);
        String sign = MD5Util.MD5Encode(sb.toString(), charset)
                .toUpperCase();
        return sign;
    }
}
